package com.software.cool.config;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.hutool.http.HtmlUtil;
import com.alibaba.fastjson.JSON;
import com.software.cool.api.admin.v1.vo.AdminLoginUserVO;
import com.software.cool.api.admin.v1.vo.AdminV1Result;
import com.software.cool.api.app.v1.vo.AppV1Result;
import com.software.cool.common.CommonContant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.PrintWriter;
import java.util.*;

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Resource
    private HttpServletRequest request;
    /**
     * 预处理回调方法，实现处理器的预处理
     * 返回值：true表示继续流程；false表示流程中断，不会继续调用其他的拦截器或处理器
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        String uri = request.getRequestURI();
//        log.info("当前路径："+uri);
        if(uri.equals("/error"))
        {
            response.sendRedirect("/page/error/404");
            return false;
        }else{
            HttpSession session = request.getSession();
            AdminLoginUserVO loginUser=null;
            String resultString="{}";
            AppV1Result appResult=new AppV1Result();
            AdminV1Result adminResult=new AdminV1Result();
            if(uri.contains("/app/v1"))
            {
                loginUser = (AdminLoginUserVO) session.getAttribute(CommonContant.APP_LOGIN_SESSION);
                appResult.setSuccess(false);
                appResult.setErrMsg("未登录");
                resultString=JSON.toJSONString(appResult);
            }else{
                loginUser = (AdminLoginUserVO) session.getAttribute(CommonContant.ADMIN_LOGIN_SESSION);
                adminResult.setCode(-1);
                adminResult.setMsg("禁止访问");
                resultString=JSON.toJSONString(adminResult);
            }
            if(loginUser==null)
            {
                try{
                    if(uri.contains("/app/v1") || uri.contains("/admin/v1"))
                    {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter printWriter=response.getWriter();
                        printWriter.write(resultString);
                        printWriter.flush();
                        printWriter.close();
                        return false;
                    }else{
                        response.sendRedirect("/login");
                        return false;
                    }

                }catch (Exception e){

                }
                return false;
            }else{
                // 如果该请求不在拦截范围内，直接返回true
                Enumeration<String> names = request.getParameterNames();
                while(names.hasMoreElements()){
                    String name = names.nextElement();
                    String[] values = request.getParameterValues(name);
                    for(String value: values){
                        //sql注入直接拦截
                        if(judgeSQLInject(value.toLowerCase())){
                            response.setContentType("application/json;charset=utf-8");
                            PrintWriter printWriter=response.getWriter();
                            if(uri.contains("/admin/v1"))
                            {
                                adminResult.setCode(1);
                                adminResult.setMsg("参数含有非法攻击字符,已禁止继续访问！");
                                printWriter.write(JSON.toJSONString(adminResult));
                            }else{
                                appResult.setErrMsg("参数含有非法攻击字符,已禁止继续访问！");
                                printWriter.write(JSON.toJSONString(appResult));
                            }
                            printWriter.flush();
                            printWriter.close();
                            return false;
                        }
                        //跨站xss清理
                        HtmlUtil.filter(value);
                    }
                }
                return true;
            }
        }


    }

    /**
     * 后处理回调方法，实现处理器（controller）的后处理，但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }
    /**
     * 整个请求处理完毕回调方法，即在视图渲染完毕时回调，
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间，
     * 还可以进行一些资源清理，类似于try-catch-finally中的finally，
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }

    /**
     * 从request中获得参数Map，并返回可读的Map
     *
     * @param request
     * @return
     */
    protected Map getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        Map returnMap = new HashMap();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if(null == valueObj){
                value = "";
            }else if(valueObj instanceof String[]){
                String[] values = (String[])valueObj;
                for(int i=0;i<values.length;i++){
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length()-1);
            }else{
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }

    /**
     * ip地址
     * @param request
     * @return
     */
    public  String getIpAddr(HttpServletRequest request)  {
        String ip  =  request.getHeader( " x-forwarded-for " );
        if (ip  ==  null   ||  ip.length()  ==   0   ||   " unknown " .equalsIgnoreCase(ip))  {
            ip  =  request.getHeader( " Proxy-Client-IP " );
        }
        if (ip  ==   null   ||  ip.length()  ==   0   ||   " unknown " .equalsIgnoreCase(ip))  {
            ip  =  request.getHeader( " WL-Proxy-Client-IP " );
        }
        if (ip  ==   null   ||  ip.length()  ==   0   ||   " unknown " .equalsIgnoreCase(ip))  {
            ip  =  request.getRemoteAddr();
        }
        return  ip;
    }

    /**
     * 判断参数是否含有攻击串
     * @param value
     * @return
     */
    public boolean judgeSQLInject(String value){
        if(value == null || "".equals(value)){
            return false;
        }
        String xssStr = "select|update|delete|drop|truncate|window|location|javascript|%20|=|--|;|'|%|#|+|//| |\\\\|!=|(|)";
        String[] xssArr = xssStr.split("\\|");
        for(int i=0;i<xssArr.length;i++){
            if(value.indexOf(xssArr[i])>-1){
                log.info(value+"_"+xssArr[i]);
                return true;
            }
        }
        return false;
    }

}
